﻿#pragma once
//对网络版计算器的收尾：
//
//对 之前的网络计算器程序 进行守护进程
//
//服务器进程应该变成守护进程
//做法1：nohup + . / ........不推荐 不建议 不完美
//
//此时就算关掉了服务类程序的shell  客户端依旧可以和守护进程交互 甚至你把xshell关掉 其他人也可以在自己的电脑上运行客户端 和你的守护进程交互
//
//
//每次点开登录xshel的时候
//①： 都会给该终端打开一个终端文件 向这个文件写入 就是向该终端写入 有截图
//②：新启一个bash进程，该进程用来做命令行解释。所以每个终端都有一个bash进程
//
//pts / 0所属项叫做TTY： 代表该bash进程和哪个终端文件相关联  0就代表和0号终端文件关联。所以①②是相互有关联的
//
//而①②操作整合起来就叫做新建一个会话，会话的ID就是会话中的第一个进程，一叫做话首进程，一般就是bash进程 会话ID叫做SID；所以当当前bash进程启动任何程序之后，此进程一定是属于对应bash会话的！此时该程序的SID一定是bash的pid！
//
//而当我们关闭shell的时候，那么会话就会被释放，该会话里面的进程都会被终止退出，这就意味着如果服务端程序位于某个会话中，那么关闭xshell就会让服务端程序终止掉！我们应该避免这种情况的发生！ 这就是守护进程存在的意义！
//
//电脑很卡的时候，不一定需要重启，也可能只需注销，windows中的注销就是释放一个会话，每个用户登陆都是会有自己的会话，注销可以关掉会话里面的进程
//
//所以我们需要把服务端进程放进一个新的会话中，此时我们关闭xshell也不会影响到新的会话了，setsid系统调样接口即可。setsid就会创建一个新的会话，并且让调用该接口的进程成为该会话的话首进程！
//
//但是有一个限制条件，不能被进程组的组长调用setsid接口
//
//进程组：有血缘关系，父子，爷孙，兄弟的进程的整体就叫做进程组！有可能是fork创建的进程，也有可能是管道创建的兄弟进程；进程组中的进程一般会互相协助地完成一个进程！
//
//而我们的服务端程序就是自成一组的，自己是组长，因为它没有具有血缘关系的其他进程！所以我们只需在服务器端代码中，fork之后，里面让父进程退出，此时的子进程就可以调用setsid了，因为子进程不是组长，此时的子进程就是守护进程(精灵进程)，其所属一个独立的会话中，守护进程一定是孤儿进程，所以其的回收也不用在意
//
//我们也不用自己的手动的通过代码去做fork退出父进程等操作，因为可以直接使用daemon接口，哪个进程调用该操作，那么哪个进程就变成守护进程！
//
//-------------------- -
//int daemon(int nochdir, int noclose);
//nochdir：是否需要更改守护进程的工作目录？要则变到 / 根目录，不则启动所在的路径(cwd)
//noclose：是否需要进行输入输出的处理？要则代表012三个流重定向到 / dev / null中，相当于丢弃了守护进程的所有输入输出，
//
//两个参数：0代表要，1代表不要，双重否定表肯定
//----------------------
/// dev / null文件，任何Linux系统都会存在的一个文件，特点是读不到任何东西，写进去的东西也会被丢弃
//
//守护进程一般会去关联终端文件，TTY就是问号，本质就是不关心也不需要打印，不需要输入输出！而我们的服务器进程也可以满足这一点，因为我们启动之后，只需从套接字中读取数据和返回数据即可，不需要输出输入什么的。
//
//daemon(0, 0)和daemon(1, 1)，的效果都在截图中，daemon(1, 1)后者虽然也是守护进程，但是其工作目录不变，其仍然和终端文件有关联，输入输出会打印到该终端文件中！
//
//所以我们在服务端main.cc中使用daemon(0, 0)即可，另外我们还想看到日志，所以只需使用enablefile接口，把日志打印到指定的文件中即可，但是一但第一个参数为0，代表你的日志文件将会在根目录中生成，肯定会失败的，所以此时只能由root 或者sudo去运行服务端 才会在根目录生成log.txt
//但是我们期望的不是这样，所以一般我们放在 / var / log / 中！
//
//这就叫把服务部署在了云服务器上，守护进程的意义所在
//
//------------------------------------------------------------------------------------ -
//应用层协议----->HTTP协议：
//
//不管应用层协议是什么，只要你的传输层用的是TCP协议，则必定离不开序列化和黏报问题的解决策略
//
//虽然我们说, 应⽤层协议是我们程序猿⾃⼰定的.比如之前的Socket程序，我们UDP就明确了协议类型是字符串，之后的TCP我们明确了协议类型是结构体，但是但实际上, 已经有⼤佬们定义了⼀些现成的, ⼜⾮常好⽤的应⽤层协议, 供我们直接参考使⽤.HTTP(超⽂本传输协议)就是其中之⼀
//
//Q：协议无非就是规定一种类型，再添加报头，还能牛到哪里去？
//
//超⽂本：文本，图片，音频，视频等都可以传输
//
//HTTP协议是⼀个⽆连接、⽆状态的协议，即每次请求都需要建⽴新的连接，
//且服务器不会保存客⼾端的状态信息。此话暂时无法理解
//
//HTTP协议是基于TCP协议的，两个连接的概念不同
//
//----------------------------------------
//我们从服务器中获取到的资源，在未被获取之前，存储在哪里，必然实在服务器上的，而Linux下一切皆文件，所以在资源必定是在服务器的文件之中的！
//
//所以获取资源，就是获取文件的内容，所以先要找到对应的文件，那如何找到对应的文件？根据路径即可？不仅仅需要路径，而是先要找到对应的服务器，ip + port即可！ 再根据路径找到指定文件！即可找到唯一服务器的唯一文件
//也就是可以找到互联网中的唯一的资源！
//
//所以一个网址就是 协议 + ip(port) + 路径，就是一个定位的方式，所以URL叫做统一资源定位符
//
//细节1：但是问题是我们发现大部分网址的协议都叫做https？？因为https囊括了http，但https更安全，会对数据加密和解密，所以我们先学懂http即可
//
//细节2：域名代表ip，端口号呢？一般网址的port都是明确的，知名的，已经规定好的，所以不明面显示，省略了；没规定的需要 : 80这样子
//
//URL的urlencode和urldecode(了解) 截图中有
//
//----------------------------------------
//Q：清华大学为什么在URL中变成 % E6这种样式了？
//编码：就是把语言(符号)进行编号罢了，你就是1 我就是2 这样....，所以每个汉字都可以映射到一个数字上，所以ascll码表也是类似的道理，无非就是对英文字母进行编号拔了，而中文就是对汉字进行编号罢了.......一个道理，都是(语言)符号和数字的映射！这就是为什么 % c打印65 是a的原因，因为映射
//
//而ascll码表仅仅是英语这种语言的映射，要想让世界的所有语言都能映射为一个数字，则需要utf8这种编码方式，其拥有更多的映射关系！
//
//A：所以为什么清华大学会显示为16进制，因为从编码的角度，任何语言都是符号，符号都会被映射到一个数字，而数字必然可以转化为16进制！因为计算机只认识二进制....
//
//可以用URL编码解码工具进行验证
//------------------------------------------------------------------------------------ -
//3：直接写HTTP的代码
//
//我们先获取一下HTTP的请求，也就是看看HTTP发过来的类型的结构是什么
//所以直接使用套接字的封装文件即可，方便！
//
//我们不想再像网络计算器那样 三层结构 而是在服务器所bind的函数所在类中 完成一切额外的操作 所以我们的服务器的回调函数的格式需要改一下，改成参数为一个字符串，返回一个字符串  因为HTTP不需要关心客户端的信息
//
//所以读写我们就在线程函数中进行，因为我们的服务类的成员变量，哪个父类指针可以直接调用多态函数，所以我们只是单纯的吧_http_service放在另一个类中，IO直接在线程函数中进行；顺便封装一下关闭fd的接口 显得优雅一点；而此时线程函数获取到的就是请求，把请求作为参数传给_http_service获取到的返回值就是响应！
//
//为什么要在线程函数去进行IO？会存在读取不完整的情况的？是的，但是我们现在不做，因为我们需要学完http才知道怎么使用接口
//
//我们完全不需要客户端 因为我们直接可以使用浏览器来充当客户端 只要支持http协议的都可以充当客户端 只需在网址处输入
//
//此时我们的服务端可以看见客户端发来的信息，因为我们仅仅只是打印了http协议发来的请求
//---------------------------------------- -
//首先http协议可以不依靠任何第三方库 比如json
//
//通过观察http的请求
//①：http的请求本质是一行长的字符串！间隔符为\r\n  ；其中的第一行叫作请求行，第二行到空行之前叫做请求报头，统称为报头
//②：最后一行空行是报头和有效载荷的分割行 现在暂无有效载荷
